package uebung08;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;

import crap.Pair;

import tools.ColorConversions;
import tools.Image;

public class Hough01 {
	public static void main(String[] args) throws Exception {
		final BufferedImage bi = ImageIO.read(Hough01.class.getClassLoader().getResourceAsStream("res/rauschen.png"));
//		final BufferedImage bi = ImageIO.read(Hough01.class.getClassLoader().getResourceAsStream("res/lines01.png"));
//		final BufferedImage bi = ImageIO.read(Hough01.class.getClassLoader().getResourceAsStream("res/lines02.png"));
		
		int[] lum = ColorConversions.getFastLuminance(bi.getRGB(0, 0, bi.getWidth(), bi.getHeight(), new int[bi.getWidth()*bi.getHeight()], 0, bi.getWidth()), new int[bi.getWidth()*bi.getHeight()]);
		
		
		final int angle_resolution = 1001, distance_resolution = 1001	;
		double[] houghVotes = new double[angle_resolution*distance_resolution];

		final int w = bi.getWidth(), h = bi.getHeight();
		
		double w2 = w/2., h2 = h/2., R = Math.sqrt(w2*w2+h2*h2), oneOverTwoTimesR = 0.5/R;
		
//		R = Math.sqrt(w*w+h*h);
		
		for (int y = 0; y < bi.getHeight(); y++) {
			for (int x = 0; x < bi.getWidth(); x++) {
				if (lum[x+y*bi.getWidth()]>192) {
					double x_ = x-w2, y_ = y-h2;
//					double x_ = x, y_ = y;

					int counter = 0;
					
					for (double theta = 0, stepTheta = Math.PI/angle_resolution; theta < Math.PI; theta += stepTheta, counter++) {
					
						double xt = Math.sin(theta)*x_, yt = Math.cos(theta)*y_;
						
						double r = (xt+yt+R)*oneOverTwoTimesR;
						
						int ro = (int) (r*(distance_resolution-1));
						
						houghVotes[counter+ro*angle_resolution]+=1;
						
					}
				}
			}
		}
		
		final BufferedImage show = new BufferedImage(angle_resolution, distance_resolution, BufferedImage.TYPE_INT_ARGB);
		double sum = 0, count = 0, max = Double.NEGATIVE_INFINITY; 
		double[] nms = new double[angle_resolution*distance_resolution];
		for (int y = 1; y<distance_resolution-1; y++) {
			for (int x = 1; x<angle_resolution-1; x++) {
				
				double value = houghVotes[x+y*angle_resolution], upper = houghVotes[x+(y+1)*angle_resolution], lower = houghVotes[x+(y-1)*angle_resolution], left = houghVotes[x-1+y*angle_resolution], right = houghVotes[x+1+y*angle_resolution], upperright = houghVotes[x+1+(y+1)*angle_resolution], upperleft = houghVotes[x-1+(y+1)*angle_resolution], lowerleft = houghVotes[x-1+(y-1)*angle_resolution], lowerright = houghVotes[x+1+(y-1)*angle_resolution];
				
				if (value > upper && value > lower && value > right && value > left && value > lowerleft && value > lowerright && value > upperleft && value > upperright) {
					nms[x+y*angle_resolution] = value;
					count ++;
					sum += value;
					max = Math.max(value, max);
				}
			}
		}
//		System.out.println(max);
		double threshold = 150; //(sum/count;
		for (int y = 0; y<distance_resolution; y++) {
			for (int x = 0; x<angle_resolution; x++) {
				
				if (nms[x+y*angle_resolution]<threshold) {
					nms[x+y*angle_resolution] = 0;
				}
			}
		}
		final ArrayList<Pair<Point2D, Point2D>> lines = new ArrayList<Pair<Point2D,Point2D>>();
		final double scale = 100;
		for (int y = 0; y<distance_resolution; y++) {
			for (int x = 0; x<angle_resolution; x++) {
				
				if (Double.compare(nms[x+y*angle_resolution], 0) != 0) {
					double theta = x/(double)angle_resolution, r = y/((double)distance_resolution-1.)/oneOverTwoTimesR-R;
					
					System.out.println(r+" "+theta+" "+Math.toDegrees(theta));
					
					double y_ = r/Math.sin(theta), x_ = r/Math.cos(theta);
					
					System.out.println(x_ +" "+y_);
//					lines.add(new Pair<Point2D, Point2D>(new Point2D.Double(x_*scale+y_+w2, -y_*scale+x_+h2), new Point2D.Double(y__+w2, x__+h2)));
					lines.add(new Pair<Point2D, Point2D>(new Point2D.Double(w2, h2), new Point2D.Double(x_+w2, y_+h2)));
				}
			}
		}
		for (Pair<Point2D, Point2D> p : lines) {
			System.out.println(p.a+ " "+ p.b);
		}
		int[] grey = new int[angle_resolution*distance_resolution];
		grey = Image.prepare(nms, grey);
		
		int[] pixels = Image.buildRGB(grey, grey, grey, new int[angle_resolution*distance_resolution]);
		
		show.setRGB(0, 0, show.getWidth(), show.getHeight(), pixels, 0, show.getWidth());
		    
		JFrame ff = new JFrame();
		ff.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		ff.add(new JComponent() {
			{setPreferredSize(new Dimension(bi.getWidth(), bi.getHeight()));}
			Line2D line = new Line2D.Double();
			@Override
			public void paint(Graphics g) {
				
				super.paint(g);
				
				g.drawImage(bi, 0, 0, this);
				Graphics2D g2 = (Graphics2D)g;
				g2.setColor(Color.red);
				for (Pair<Point2D, Point2D> p : lines) {
					line.setLine(p.a, p.b);
					g2.draw(line);
				}
			}
		});
		
		ff.pack();
		ff.setVisible(true);
		
	}
}
